package jwlee.testnetwork;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.ServerSocket;
import java.net.Socket;

import javax.swing.JFileChooser;

/**
 * 该类用到的帮定端口初始为10000如果绑定不成功试另外的端口 绑定次数用tryBindTimes表识如果帮定失败会对它加一的
 * 当前帮定端口由DefaultBindPort+tryBindTimes决定 外界系统(调用此程序的对象)可以获取当前的帮定端口
 * 并告诉客户端服务的端口号以使其能正确连接到该端口上
 */
public class FileRecverServer extends Thread {
	ServerSocket serverSocket; // 服务套接字等待 对方的连接和文件发送
	Socket socket; // 由服务套接字产生的 套接字
	InputStream is; // 用于读取

	RandomAccessFile inFile = null; // 随机访问文件
	byte byteBuffer[] = new byte[1024];// 临时缓寸区

	int defaultBindPort = 10000;// 默认用10000端口监听请求
	int tryBindTimes = 0; // 初始的绑定端口次数为0
	int currentBindPort = defaultBindPort + tryBindTimes;// 当前绑定的端口号是10000默认端口

	private void bindToServerPort() throws Exception {
		try {
			// 在自己的机器上开一个服务类套接字并等待发送者的连接
			serverSocket = new ServerSocket(this.currentBindPort);
		} catch (Exception e) {
			this.tryBindTimes++;
			this.currentBindPort = this.defaultBindPort + this.tryBindTimes;
			if (this.tryBindTimes >= 20) {
				throw new Exception("无法绑定到指定端口" + '\n' + "试了太多次了!");
			}
			this.bindToServerPort();// 递归的绑定
		}
		System.out.println("成功绑定的端口号是:" + this.currentBindPort);
	}

	public int getTryBindedTimes() {
		return this.tryBindTimes;
	}

	public int getCurrentBindingPort() {
		return this.currentBindPort;
	}

	public static void main(String args[]) {
		new FileRecverServer().start();
	}

	public FileRecverServer() {
		try {
			this.bindToServerPort();// 绑定服务的端口
		} catch (Exception e) {// 绑定端口不成功
			e.printStackTrace();
			System.exit(1);
		}
	}

	private void showFileChooser() {
		JFileChooser jfc = new JFileChooser("c:/");// 文件选择器 以当前的目录打开
		jfc.showSaveDialog(new javax.swing.JFrame());
		File savedFile = jfc.getSelectedFile(); // 获取当前的选择文件引用

		if (savedFile != null) {
			// 用以读取数据的随机访问文件,可以每次以块的方式读取数据
			try {
				inFile = new RandomAccessFile(savedFile, "rw");
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			}
		}
	}

	public void run() {
		try {
			System.out.println("wait for...");
			socket = serverSocket.accept(); // 等待对方的连接
			this.serverSocket.setSoTimeout(5000);// 五秒钟连不上将抛出异常
			if (this.inFile == null) {
				showFileChooser();
			}
			this.is = socket.getInputStream(); // 获取输入流
		} catch (Exception ex) {
			ex.printStackTrace();
			return;
		}

		int amount; // 以下为传送文件代码 和流 套接字清理工作
		try {
			if (this.inFile == null) {
				System.out.println("没有选择文件");
				this.serverSocket.close();// 关闭服务方套接字
				return; // 没有选择文件
			}
			while ((amount = is.read(byteBuffer)) != -1) {
				inFile.write(byteBuffer, 0, amount);
			}

			is.close(); // 关闭流
			javax.swing.JOptionPane.showMessageDialog(new javax.swing.JFrame(),
					"已接收成功", "提示!", javax.swing.JOptionPane.PLAIN_MESSAGE);
			System.out.println("接收完毕!");
			inFile.close(); // 关闭文件
			socket.close(); // 关闭临时套接字
			this.serverSocket.close();// 关闭服务方套接字
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}